package trigger

import (
	"bgs/db"
	sqlc "bgs/db/sqlc"
	nsqpUtil "bgs/nsqp/util"
	ledgerService "bgs/service/ledger"
	model "bgs/service/model"
	"bgs/util"
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"github.com/nsqio/go-nsq"
	"go.uber.org/zap"
	"strconv"
)

// AddProfitReceiverHandler 添加分账者 handler
type AddProfitReceiverHandler struct {
	dao           *db.PgDao
	slog          *zap.SugaredLogger
	topic         string
	failover      *nsqpUtil.NsqFailover
	ledgerService *ledgerService.LedgerServiceImp
}

// NewAddProfitReceiverHandler create a new handler for add profit receiver
func NewAddProfitReceiverHandler(
	pgdao *db.PgDao,
	slog *zap.SugaredLogger,
	topic string,
	failover *nsqpUtil.NsqFailover,
	ledgerService *ledgerService.LedgerServiceImp,
) *AddProfitReceiverHandler {
	return &AddProfitReceiverHandler{
		dao:           pgdao,
		slog:          slog.With("module", "AddProfitReceiverHandler"),
		topic:         topic,
		failover:      failover,
		ledgerService: ledgerService,
	}
}

// HandleMessage implements the Handler interface.
func (h *AddProfitReceiverHandler) HandleMessage(m *nsq.Message) error {
	if len(m.Body) == 0 {
		// Returning nil will automatically send a FIN command to NSQ to mark the message as processed.
		return nil
	}

	h.slog.Infof("AddProfitReceiverMessage=>%s", string(m.Body))

	v := &model.ProfitReceiver{}
	if decodeErr := json.NewDecoder(bytes.NewReader(m.Body)).Decode(v); decodeErr != nil {
		return fmt.Errorf("无法解析信息[AddProfitReceiverMessage]: %v", decodeErr)
	}

	reqID := strconv.FormatInt(v.Timestamp, 10)
	ctx := context.WithValue(context.Background(), util.RequestID{}, reqID)

	var err error
	defer h.failover.BackupSubMsgWhenHandleFail(ctx, &err, nsqpUtil.BackupSubMsgParam{
		Ts:    v.Timestamp,
		Topic: h.topic,
		Mbody: m.Body,
	})

	err = h.dao.NewTxRunner().SqlcExecTx(ctx, func(q *sqlc.Queries) (err error) {
		h.slog.Infof("a AddProfitReceiverHandler ok")
		err = h.ledgerService.AddProfitReceiver(ctx, v)
		if err != nil {
			return
		}
		return
	})

	if err != nil {
		return err
	}
	// Returning a non-nil error will automatically send a REQ command to NSQ to re-queue the message.
	return nil
}